import mongoose, { Document, Schema, Model } from 'mongoose';

/**
 * 部门接口定义
 * 定义部门的基本属性和结构
 */
export interface IDepartment {
  /** 部门名称 */
  name: string;
  /** 部门描述 */
  description?: string;
  /** 所属团队ID */
  teamId: mongoose.Types.ObjectId;
  /** 部门经理ID */
  managerId?: mongoose.Types.ObjectId;
  /** 状态：1-正常，0-禁用 */
  status: number;
  /** 创建时间 */
  createdAt: Date;
  /** 更新时间 */
  updatedAt: Date;
}

/**
 * 部门文档接口
 * 继承IDepartment接口和mongoose的Document接口
 */
export interface IDepartmentDocument extends IDepartment, Document {
  /** 转换为JSON格式，用于API响应 */
  toJSON(): any;
}

/**
 * 部门模型接口
 * 定义部门模型的静态方法
 */
export interface IDepartmentModel extends Model<IDepartmentDocument> {
  /**
   * 根据部门名称查找部门
   * @param name 部门名称
   * @returns 部门文档或null
   */
  findByName(name: string): Promise<IDepartmentDocument | null>;
  
  /**
   * 根据团队ID查找部门
   * @param teamId 团队ID
   * @returns 部门文档数组
   */
  findByTeam(teamId: mongoose.Types.ObjectId): Promise<IDepartmentDocument[]>;
  
  /**
   * 根据经理ID查找部门
   * @param managerId 经理ID
   * @returns 部门文档数组
   */
  findByManager(managerId: mongoose.Types.ObjectId): Promise<IDepartmentDocument[]>;
  
  /**
   * 根据状态查找部门
   * @param status 状态值
   * @returns 部门文档数组
   */
  findByStatus(status: number): Promise<IDepartmentDocument[]>;
}

/**
 * 部门数据模型Schema定义
 * 定义部门在MongoDB中的数据结构
 */
const DepartmentSchema = new Schema<IDepartmentDocument>({
  // 部门名称，必填，最大长度100
  name: {
    type: String,
    required: [true, '部门名称不能为空'],
    trim: true,
    maxlength: [100, '部门名称不能超过100个字符'],
    index: true
  },
  
  // 部门描述，可选，最大长度500
  description: {
    type: String,
    trim: true,
    maxlength: [500, '部门描述不能超过500个字符']
  },
  
  // 所属团队ID，必填，引用团队表
  teamId: {
    type: Schema.Types.ObjectId,
    ref: 'Team',
    required: [true, '所属团队不能为空'],
    index: true
  },
  
  // 部门经理ID，可选，引用用户表
  managerId: {
    type: Schema.Types.ObjectId,
    ref: 'User',
    index: true
  },
  
  // 状态：1-正常，0-禁用，默认为1
  status: {
    type: Number,
    required: true,
    enum: [0, 1],
    default: 1,
    index: true
  }
}, {
  // 自动添加创建时间和更新时间
  timestamps: true,
  // 设置集合名称
  collection: 'departments'
});

/**
 * 团队内部门名称唯一性索引
 * 确保同一团队内部门名称唯一
 */
DepartmentSchema.index({ teamId: 1, name: 1 }, { unique: true });

/**
 * 复合索引：状态和创建时间
 * 用于按状态和时间排序查询
 */
DepartmentSchema.index({ status: 1, createdAt: -1 });

/**
 * 团队和状态复合索引
 * 用于快速查找团队下的活跃部门
 */
DepartmentSchema.index({ teamId: 1, status: 1 });

/**
 * 经理索引
 * 用于快速查找某个经理管理的部门
 */
DepartmentSchema.index({ managerId: 1 });

/**
 * 保存前中间件
 * 在保存部门数据前进行数据验证和处理
 */
DepartmentSchema.pre('save', function(next) {
  // 如果是新文档或名称被修改，进行名称格式验证
  if (this.isNew || this.isModified('name')) {
    // 部门名称不能包含特殊字符
    const nameRegex = /^[\u4e00-\u9fa5a-zA-Z0-9\s\-_]+$/;
    if (!nameRegex.test(this.name)) {
      return next(new Error('部门名称只能包含中文、英文、数字、空格、横线和下划线'));
    }
  }
  
  next();
});

/**
 * 更新前中间件
 * 在更新部门数据前进行数据验证
 */
DepartmentSchema.pre(['updateOne', 'findOneAndUpdate'], function(next) {
  const update = this.getUpdate() as any;
  
  // 如果更新名称，进行格式验证
  if (update.name || (update.$set && update.$set.name)) {
    const name = update.name || update.$set.name;
    const nameRegex = /^[\u4e00-\u9fa5a-zA-Z0-9\s\-_]+$/;
    if (!nameRegex.test(name)) {
      return next(new Error('部门名称只能包含中文、英文、数字、空格、横线和下划线'));
    }
  }
  
  next();
});

/**
 * 实例方法：转换为JSON格式
 * 用于API响应时隐藏敏感信息
 */
DepartmentSchema.methods.toJSON = function() {
  const obj = this.toObject();
  
  // 返回部门信息，包含所有字段
  return {
    _id: obj._id,
    name: obj.name,
    description: obj.description,
    teamId: obj.teamId,
    managerId: obj.managerId,
    status: obj.status,
    createdAt: obj.createdAt,
    updatedAt: obj.updatedAt
  };
};

/**
 * 静态方法：根据部门名称查找部门
 * @param name 部门名称
 * @returns 部门文档或null
 */
DepartmentSchema.statics.findByName = function(name: string): Promise<IDepartmentDocument | null> {
  return this.findOne({ name: name.trim() }).exec();
};

/**
 * 静态方法：根据团队ID查找部门
 * @param teamId 团队ID
 * @returns 部门文档数组
 */
DepartmentSchema.statics.findByTeam = function(teamId: mongoose.Types.ObjectId): Promise<IDepartmentDocument[]> {
  return this.find({ teamId }).sort({ createdAt: -1 }).exec();
};

/**
 * 静态方法：根据经理ID查找部门
 * @param managerId 经理ID
 * @returns 部门文档数组
 */
DepartmentSchema.statics.findByManager = function(managerId: mongoose.Types.ObjectId): Promise<IDepartmentDocument[]> {
  return this.find({ managerId }).sort({ createdAt: -1 }).exec();
};

/**
 * 静态方法：根据状态查找部门
 * @param status 状态值
 * @returns 部门文档数组
 */
DepartmentSchema.statics.findByStatus = function(status: number): Promise<IDepartmentDocument[]> {
  return this.find({ status }).sort({ createdAt: -1 }).exec();
};

/**
 * 创建并导出部门模型
 * 使用DepartmentSchema创建Department模型
 */
export const Department = mongoose.model<IDepartmentDocument, IDepartmentModel>('Department', DepartmentSchema);

// 默认导出Department模型
export default Department;